﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Web;
using System.Web.Mvc;
using System.Linq;
using OurSite.WebAdmin.Models;
using OurSite.Business.Category;
using OurSite.Business.Event;
using OurSite.Business.Picture;
using OurSite.Business.Repositories;
using OurSite.Business.Helper;
using OurSite.WebAdmin.HTMLHelpers;

namespace OurSite.WebAdmin.Controllers
{
    public class EventController : BaseController
    {
        IEventRepository eventRepository = new EventRepository();
        ICategoryRepository categoryRepository = new CategoryRepository();
        IPictureRepository pictureRepository = new PictureRepository();
        IPeopleRepository peopleRepository = new PeopleRepository();

        #region ActionResults

        [Authorize]
        public ActionResult Index()
        {
            IEventRepository repository = new EventRepository();
            var evtYears = repository.GetDistinctYears();
            SelectList yearList = new SelectList(evtYears);
            ViewData["EventYears"] = yearList;

            return View();
        }

        [Authorize]
        public ActionResult EditEvent(int? id)
        {
            if (id == null)
                return View("EventNotFound");

            int eventCode = (int) id;
            ViewData["EventSaveMessage"] = TempData["EventSaveMessage"];
            return View(BuildBaseModel(eventCode));
        }

        [Authorize]
        [HttpPost]
        public ActionResult EditEvent(EventModel eventModel)
        {
            var facebookRemoved = new List<int>();
            var facebookChanged = new List<int>();

            Event evt = new Event();
            if (ModelState.IsValid)
            {
                if (eventModel.EventId == Guid.Empty)
                {
                    #region Create New
                    try
                    {
                        IEventRepository repository = new EventRepository();
                        evt = new Event
                        {
                              EventCode = repository.GetNextEventCode(),
                              ParentId = eventModel.ParentId,
                              Name = eventModel.EventName,
                              StartDate = Convert.ToDateTime(eventModel.StartDate),
                              EndDate = Convert.ToDateTime(eventModel.EndDate),
                              ShortDescription = eventModel.ShortDescription,
                              LongDescription = eventModel.LongDescription,
                              Region = eventModel.Region,
                              Country = eventModel.Country,
                              State = eventModel.State,
                              City = eventModel.City,
                              Location = eventModel.Location,
                              Order = eventModel.Order,
                              AlternateURL = eventModel.AlternateURL
                          };
                        repository.Add(evt);

                        TempData["EventSaveMessage"] = "Create was successful.";
                    }
                    catch (Exception ex)
                    {
                        TempData["EventSaveMessage"] = "An Error has occurred. " + ex.Message;
                    }
                    #endregion
                }
                else
                {
                    #region Update
                    try
                    {
                        IEventRepository repository = new EventRepository();
                        evt = repository.GetById(eventModel.EventId);
                        evt.ParentId = eventModel.ParentId;
                        evt.Name = eventModel.EventName;
                        evt.StartDate = Convert.ToDateTime(eventModel.StartDate);
                        evt.EndDate = Convert.ToDateTime(eventModel.EndDate);
                        evt.ShortDescription = eventModel.ShortDescription;
                        evt.LongDescription = eventModel.LongDescription;
                        evt.Region = eventModel.Region;
                        evt.Country = eventModel.Country;
                        evt.State = eventModel.State;
                        evt.City = eventModel.City;
                        evt.Location = eventModel.Location;
                        evt.Order = eventModel.Order;
                        evt.AlternateURL = eventModel.AlternateURL;
                        
                        
                        for (int picCount = 0; picCount < evt.Pictures.Count;picCount++)
                        {
                            Picture p = evt.Pictures[picCount];
                            if (Request.Form["delete_" + p.PictureCode].Contains(p.PictureCode.ToString()))
                            {
                                evt.Pictures.Remove(p);
                                if(!string.IsNullOrEmpty(p.FacebookId))
                                    facebookRemoved.Add(picCount);
                            }
                            else
                            {
                                p.Caption = Request.Form["caption_" + p.PictureCode];
                                p.IsListing = Request.Form["islisting"] == p.PictureCode.ToString();
                                p.IsFavorite = Request.Form["isFavorite_" + p.PictureCode].Contains("true");
                                p.Order = Convert.ToInt32(Request.Form["order_" + p.PictureCode]);

                                if (Request.Form["isfacebook_" + p.PictureCode].Contains("true"))
                                    facebookChanged.Add(picCount);
                                else
                                    facebookRemoved.Add(picCount);
                            }
                        }

                        
                        evt = UpdateFacebook(evt, facebookRemoved, facebookChanged);
                        repository.Update(evt);

                        TempData["EventSaveMessage"] = "Update was successful.";
                    }
                    catch (Exception ex)
                    {
                        TempData["EventSaveMessage"] = "An Error has occurred. " + ex.Message;
                    }
                    #endregion
                }
            }
            else
            {
                return View(BuildBaseModel(eventModel.EventCode));
            }

            return RedirectToAction("EditEvent", new { id = evt.EventCode });
        }

        [Authorize]
        public ActionResult ListingOverView()
        {
            #region Decades
            IList<Event> decadeEvents = BuildDecades();
            #endregion

            #region Region
            IList<Event> regionEvents = new List<Event>();
            var regions = eventRepository.GetDistinctRegions(string.Empty);

            foreach (string region in regions)
            {
                Event evt = new Event();
                evt.Name = region;
                evt.ListingPicture = pictureRepository.GetRegionListingPicture(region);
                if(region == "North America")
                {
                    var states = eventRepository.GetDistinctStates("United States", string.Empty);
                    foreach (string state in states)
                    {
                        Event subevt = new Event();
                        subevt.Name = state;
                        subevt.ListingPicture = pictureRepository.GetStateListingPicture(state); 
                        evt.SubEvents.Add(subevt);
                    }

                }

                regionEvents.Add(evt);
            }
            #endregion

            #region People
            IList<Event> peopleEvents = BuildPeople();           
            #endregion
            
            #region Parent Categories
            var categories = categoryRepository.GetAllParentCategories();
            IList<Event> categoryEvents = new List<Event>();
            foreach(Category category in categories)
            {
                Event evt = new Event();
                evt.Id = category.Id;
                evt.Name = category.Name;
                evt.ListingPicture = pictureRepository.GetCategoryListingPicture(category.Name);

                categoryEvents.Add(evt);
            }
            #endregion

            ListingImages listingImage = new ListingImages();
            listingImage.Decades = decadeEvents;
            listingImage.Regions = regionEvents;
            listingImage.People = peopleEvents;
            listingImage.ParentCategories = categoryEvents;
            
            return View(listingImage);
        }

        [Authorize]
        public ActionResult ListingImageEdit(string type, string name)
        {
            ListingImageEdit listingImageEdit = new ListingImageEdit();

            switch(type)
            {
                case "Decades":
                    string start = HelperUtilities.ReverseURLFriendly(name).Substring(6, 4);
                    string end = HelperUtilities.ReverseURLFriendly(name).Substring(13, 4);
                    listingImageEdit.Name = name;
                    listingImageEdit.Type = type;
                    listingImageEdit.CurrentLisingImage = pictureRepository.GetDecadeListingPicture(start, end);
                    listingImageEdit.PossibleLisingImage = pictureRepository.GetDecadeAllListingPicture(start, end);
                    break;
                case "Regions":
                    listingImageEdit.Name = name;
                    listingImageEdit.Type = type;
                    listingImageEdit.CurrentLisingImage = pictureRepository.GetRegionListingPicture(name);
                    listingImageEdit.PossibleLisingImage = pictureRepository.GetRegionAllListingPicture(name);
                    break;
                case "States":
                    listingImageEdit.Name = name;
                    listingImageEdit.Type = type;
                    listingImageEdit.CurrentLisingImage = pictureRepository.GetStateListingPicture(name);
                    listingImageEdit.PossibleLisingImage = pictureRepository.GetStateAllListingPicture(name);
                    break;
                case "People":
                    break;
                case "Categories":
                    Category category = categoryRepository.GetById(new Guid(name));
                    listingImageEdit.Id = category.Id;
                    listingImageEdit.Type = type;
                    listingImageEdit.Name = category.Name;
                    listingImageEdit.CurrentLisingImage = pictureRepository.GetCategoryListingPicture(category.Name);
                    listingImageEdit.PossibleLisingImage = pictureRepository.GetCategoryAllListingPicture(category.Name);
                    break;
                default:
                    break;
            }

            return View(listingImageEdit);
        }
        #endregion

        #region Webservice Methods
        public JsonResult DisplayEvents(int year)
        {
            IEventRepository repository = new EventRepository();
            var evts = repository.GetByYear(year);
            string returnString = HTMLHelper.EventSimpleList(evts);

            return Json(returnString, JsonRequestBehavior.AllowGet);
        }

        public JsonResult GetSubCategories(Guid parentId)
        {
            ICategoryRepository repository = new CategoryRepository();
            var categories = repository.GetSubCategories(parentId);
            string returnString = HTMLHelper.CategoryOptionList(categories);

            return Json(returnString, JsonRequestBehavior.AllowGet);
        }

        public JsonResult SaveSubCategory(Guid parentId, string categoryName)
        {
            ICategoryRepository categoryRepository = new CategoryRepository();
            Category category = new Category();
            category.ParentId = parentId;
            category.Name = categoryName;
            categoryRepository.Add(category);

            return GetSubCategories(parentId);
        }

        public JsonResult SaveCategory(string categoryName)
        {
            ICategoryRepository categoryRepository = new CategoryRepository();
            Category category = new Category();
            category.Name = categoryName;
            category.ParentId = new Guid();
            categoryRepository.Add(category);

            string returnString = HTMLHelper.CategoryOptionList(categoryRepository.GetAllParentCategories());

            return Json(returnString, JsonRequestBehavior.AllowGet);
            
        }

        public JsonResult SaveEventCategory(Guid eventId, Guid categoryId)
        {
            ICategoryRepository categoryRepository = new CategoryRepository();
            categoryRepository.AddEventCategory(eventId, categoryId);

            string returnString = HTMLHelper.EventCategoryTable(categoryRepository.GetByEventId(eventId));
            return Json(returnString, JsonRequestBehavior.AllowGet);
        }

        public JsonResult DeleteEventCatgory(Guid eventId, Guid categoryId)
        {
            ICategoryRepository categoryRepository = new CategoryRepository();
            categoryRepository.DeleteEventCategory(eventId, categoryId);

            string returnString = HTMLHelper.EventCategoryTable(categoryRepository.GetByEventId(eventId));
            return Json(returnString, JsonRequestBehavior.AllowGet);
        }

        public JsonResult RegionLookup(string lookupValue)
        {
            IEventRepository repository = new EventRepository();
            var regions = repository.GetDistinctRegions(lookupValue);

            return Json(regions, JsonRequestBehavior.AllowGet);
        }

        public JsonResult CountryLookup(string region, string lookupValue)
        {
            IEventRepository repository = new EventRepository();
            var countries = repository.GetDistinctCountries(region, lookupValue);

            return Json(countries, JsonRequestBehavior.AllowGet);
        }

        public JsonResult StateLookup(string country, string lookupValue)
        {
            IEventRepository repository = new EventRepository();
            var states = repository.GetDistinctStates(country, lookupValue);

            return Json(states, JsonRequestBehavior.AllowGet);
        }

        public JsonResult CityLookup(string state, string lookupValue)
        {
            IEventRepository repository = new EventRepository();
            var cities = repository.GetDistinctCities(state, lookupValue);

            return Json(cities, JsonRequestBehavior.AllowGet);
        }

        public JsonResult SavePeople(Guid PeopleId, string FirstName, string LastName, string MaidenName, bool isHuman, DateTime? birthDate)
        {
            People person = new People();
            person.PeopleId = PeopleId;
            person.FirstName = FirstName;
            person.LastName = LastName;
            person.MaidenName = MaidenName;
            person.IsHuman = isHuman;
            person.BirthDate = birthDate;

            IPeopleRepository repository = new PeopleRepository();
            repository.Add(person);

            string returnString = HTMLHelper.PeopleCheckList(repository.GetAllPeople());
            return Json(returnString, JsonRequestBehavior.AllowGet);
        }

        public JsonResult GetPicturePeople(Guid pictureId)
        {
            IPictureRepository repository = new PictureRepository();
            var picture = repository.GetById(pictureId);

            IList<People> people = new List<People>();
            foreach (var person in picture.People)
            {
                person.Pictures = null;
                people.Add(person);
            }

            return Json(people, JsonRequestBehavior.AllowGet);
        }

        public JsonResult SavePicture(Guid pictureId, string caption, string people, int order)
        {
            string[] stringList = people.Split(',');
            List<string> peopleList = stringList.ToList();

            IPictureRepository pictureRepository = new PictureRepository();
            IPeopleRepository peopleRepository = new PeopleRepository();
            var picture = pictureRepository.GetById(pictureId);
            picture.Caption = caption;
            picture.Order = order;
            

            peopleRepository.DeletePeopleFromPicture(pictureId);
            foreach(string s in peopleList)
            {
                if (!string.IsNullOrEmpty(s))
                {
                    Guid peopleId = new Guid(s);
                    peopleRepository.AddPeopleToPicture(pictureId, peopleId);
                }
            }
            pictureRepository.Update(picture);

            return Json("got here!!", JsonRequestBehavior.AllowGet);
        }

        public JsonResult SetCategoryListingImage(string type, Guid pictureId, Guid categoryId, string name)
        {
            switch(type)
            {
                case "Decades":
                    string start = HelperUtilities.ReverseURLFriendly(name).Substring(6, 4);
                    string end = HelperUtilities.ReverseURLFriendly(name).Substring(13, 4);
                    pictureRepository.SetDecadeListingImage(pictureId, start, end);
                    break;
                case "Regions":
                    pictureRepository.SetRegionListingImage(pictureId, name);
                    break;
                case "States":
                    pictureRepository.SetStateListingImage(pictureId, name);
                    break;
                case "People":
                    break;
                case "Categories":
                    pictureRepository.SetCategoryListingImage(pictureId, categoryId);    
                    break;
                default:
                    break;
            }
            
            Picture picture = pictureRepository.GetById(pictureId);
            return Json(picture.ImagePath, JsonRequestBehavior.AllowGet);
        }
        #endregion

        #region Upload Related Methods
        public string UploadPicture(HttpPostedFileBase fileData, string EventID)
        {
            try
            {
                string prefix = ConfigurationManager.AppSettings["UploadPicturePath"];
                // Temporary upload file
                string uploadPath = prefix + "Uploads/" + Path.GetFileName(fileData.FileName);
                fileData.SaveAs(Server.MapPath(uploadPath));

                IEventRepository eventRepository = new EventRepository();
                Event evt = eventRepository.GetById(new Guid(EventID));

                // Get the Picture Path
                string webPath = Event.BuildImageBasePath(evt) + Path.GetFileName(fileData.FileName);
                string finalPath = Server.MapPath(prefix) + webPath;
                string smallfinalPath = Server.MapPath(prefix) + "Small" + webPath;

                // Get caption from the image title
                string caption = string.Empty;// ImageUtility.GetImageCaption(Server.MapPath(uploadPath));

                // Resize Image and move to final path
                ImageUtility.Resize(Server.MapPath(uploadPath), 583);
                ImageUtility.Move(Server.MapPath(uploadPath), finalPath);

                ImageUtility.Copy(finalPath, smallfinalPath);
                ImageUtility.Resize(smallfinalPath, 292);

                // Get Next PictureCode
                IPictureRepository pictureRepository = new PictureRepository();

                // Build Picture Object and Add
                Picture picture = new Picture();
                picture.EventId = new Guid(EventID);
                picture.PictureCode = pictureRepository.GetNextPictureCode();
                picture.Caption = caption;
                picture.ImagePath = webPath;
                picture.CreatedDate = DateTime.Now;
                picture.ModifiedDate = DateTime.Now;
                picture.Order = pictureRepository.GetNextOrderByEventID(picture.EventId);
                pictureRepository.Add(picture);

                return "Upload OK!";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }    

        
    }
        #endregion

        #region Protected Methods
        protected Event UpdateFacebook(Event evt, List<int> remove, List<int> change)
        {
            AEFacebook facebook = new AEFacebook();

            if (facebook.IsAuthenticated())
            {
                if (change.Count > 0 && string.IsNullOrEmpty(evt.FacebookId))
                {
                    evt.FacebookId = facebook.PostAlbum(evt.Name, evt.FullLocation);
                }

                change.ForEach(p =>
                {
                    Picture pic = evt.Pictures[p];
                    string logicalPath = Server.MapPath("/admin/" + pic.ImagePath);
                    pic.FacebookId = facebook.PostPicture(evt.FacebookId, pic.FacebookId, pic.Caption, logicalPath);
                });

                remove.ForEach(p =>
                {
                    Picture pic = evt.Pictures[p];
                    if (!string.IsNullOrEmpty(pic.FacebookId))
                    {
                        facebook.DeleteItem(pic.FacebookId);
                        pic.FacebookId = string.Empty;
                    }
                });
            }
            return evt;
        }
        protected IList<Event> BuildDecades()
        {
            IList<Event> events = new List<Event>();
            // Show by decade starting in 1990
            int startYear = 1990;
            int groupingIncrement = 10;
            int endYear = startYear + groupingIncrement;
            var years = eventRepository.GetDistinctYears();

            // create grouping Event
            Event evt = EventGrouping(startYear, endYear, "Years");
            foreach (int y in years)
            {
                if (y <= endYear)
                {
                    Event subevt = new Event();
                    subevt.Name = y.ToString();
                    evt.SubEvents.Add(subevt);
                }

                // need to increase by the increament
                if (y == endYear)
                {
                    startYear = endYear + 1;
                    endYear += groupingIncrement;
                    events.Add(evt);
                    evt = EventGrouping(startYear, endYear, "Years");
                }
            }

            return events;
        }

        protected IList<Event> BuildPeople()
        {
            IList<Event> events = new List<Event>();
            Event hardenfamilyEvents = new Event();
            hardenfamilyEvents.Name = "Harden/Morrison Family";
            hardenfamilyEvents.ListingPicture = pictureRepository.GetPeopleListingPicture(PeopleCategory.IsHardenListingImage);

            Event ryanfamilyEvents = new Event();
            ryanfamilyEvents.Name = "Ryan/Weber Family";
            ryanfamilyEvents.ListingPicture = pictureRepository.GetPeopleListingPicture(PeopleCategory.IsRyanListingImage);

            Event friendEvents = new Event();
            friendEvents.Name = "Friends";
            friendEvents.ListingPicture = pictureRepository.GetPeopleListingPicture(PeopleCategory.IsFriendListingImage);

            events.Add(hardenfamilyEvents);
            events.Add(ryanfamilyEvents);
            events.Add(friendEvents);

            return events;
        }

        protected Event EventGrouping(int start, int end, string name)
        {
            Event evt = new Event();
            evt.Name = name + " " + start + " - " + end;
            evt.ListingPicture = pictureRepository.GetDecadeListingPicture(start.ToString(), end.ToString());
            return evt;
        }

        protected EventModel BuildBaseModel(int id)
        {
            Event evt;
            ICategoryRepository categoryRepository = new CategoryRepository();
            var categories = categoryRepository.GetAllParentCategories();

            IEventRepository evtallRepository = new EventRepository();
            var parentevts = evtallRepository.GetAllEvents();

            IPeopleRepository peopleAllRepository = new PeopleRepository();
            var people = peopleAllRepository.GetAllPeople();

            if (id == 0)
            {
                evt = new Event();
                evt.StartDate = DateTime.Now;
                evt.EndDate = DateTime.Now;
            }
            else
            {
                IEventRepository evtRepository = new EventRepository();
                evt = evtRepository.GetByEventCode(id);

            }

            return new EventModel
            {
                EventId = evt.Id,
                ParentId = evt.ParentId,
                EventCode = evt.EventCode,
                EventName = evt.Name,
                ShortDescription = evt.ShortDescription,
                LongDescription = evt.LongDescription,
                AlternateURL = evt.AlternateURL,
                Region = evt.Region,
                Country = evt.Country,
                State = evt.State,
                City = evt.City,
                Location = evt.Location,
                StartDate = evt.StartDate.ToShortDateString(),
                EndDate = evt.EndDate.ToShortDateString(),
                Order = evt.Order,
                ListingPicture = evt.ListingPicture,
                Pictures = evt.Pictures,
                EventCategories = evt.EventCategories,
                ParentCategories = categories,
                ParentEvents = parentevts,
                People = people
            };
        }
        #endregion

        public ActionResult OneTimeSmallPictureResize()
        {
            return View();
        }

        [HttpPost]
        public ActionResult OneTimeSmallPictureResize(int? id)
        {
            IPictureRepository pictureRepository = new PictureRepository();
            var pictures = pictureRepository.GetAllPictures();
            string prefix = ConfigurationManager.AppSettings["UploadPicturePath"];
            try
            {
                foreach (Picture picture in pictures)
                {
                    string picPath = picture.ImagePath.Replace("/", "\\");
                    string imagePath = Server.MapPath(prefix) + picPath;
                    string newImagePath = Server.MapPath(prefix) + "Small" + picPath;
                    ImageUtility.Copy(imagePath, newImagePath);
                    ImageUtility.Resize(newImagePath, 292);
                }

                ViewData["Message"] = "Done!!";

            }
            catch(Exception ex)
            {
                ViewData["Message"] = ex.Message;
            }

            return View();
        }
    }
}